<template>
  <div class="x_form">
    <a-spin :spinning="!showForm">
      <a-form
        ref="formRef"
        :rules="rules"
        v-if="showForm"
        :model="formInfo"
        :label-col="labelCol"
        :wrapper-col="wrapperCol"
      >
        <a-row :gutter="20">
          <a-col
            v-for="item in (formDict as Array<dictType>) "
            :key="item.attr"
            :span="item.span || 12"
          >
            <template v-if="!item.label && item.slot">
              <slot :name="item.attr"></slot>
            </template>
            <a-form-item v-else :label="item.label" :name="item.attr">
              <slot :name="item.attr" :data="item" v-if="item.slot"></slot>
              <template v-else>
                <a-input
                  :disabled="item.disabled"
                  v-model:value="formInfo[item.attr]"
                  :placeholder="item.placeholder"
                  v-if="item.type == 'input'"
                  @change="(val:any) => propChange(val.target.value,item)"
                />
                <a-input
                  :disabled="item.disabled"
                  v-model:value="formInfo[item.attr]"
                  :placeholder="item.placeholder"
                  type="number"
                  v-if="item.type == 'number'"
                  @change="(val:any) => propChange(val.target.value,item)"
                />
                <a-date-picker
                  :disabled="item.disabled"
                  v-model:value="formInfo[item.attr]"
                  v-if="item.type == 'time'"
                  :format="item.format || 'YYYY-MM-DD'"
                  style="width: 100%"
                  :placeholder="item.placeholder"
                  @change="(val:any) => propChange(val, item)"
                />
                <a-range-picker
                  :disabled="item.disabled"
                  v-model:value="formInfo[item.attr]"
                  v-if="item.type == 'timeRange'"
                  valueFormat="YYYY-MM-DD"
                  :placeholder="item.placeholder"
                  style="width: 100%"
                  @change="(val:any) => propChange(val, item)"
                />
                <a-radio-group
                  @change="(val:any) => propChange(val, item)"
                  :disabled="item.disabled"
                  v-if="item.type == 'radio'"
                  name="radioGroup"
                  :placeholder="item.placeholder"
                  v-model:value="formInfo[item.attr]"
                >
                  <a-radio
                    v-for="it in item.options"
                    :key="it.value"
                    :value="it.value"
                    >{{ it.label }}</a-radio
                  >
                </a-radio-group>
                <a-select
                  :placeholder="item.placeholder"
                  :disabled="item.disabled"
                  v-model:value="formInfo[item.attr]"
                  v-if="item.type == 'select' && item.mode !== 'multiple'"
                  @change="(val:any) => propChange(val, item)"
                >
                  <template v-if="item.options && item.options.length > 0">
                    <a-select-option
                      v-for="oitem in item.options"
                      :title="oitem.label"
                      :value="oitem.value"
                      :key="oitem.value"
                      >{{ oitem.label }}</a-select-option
                    >
                  </template>
                </a-select>
                <a-select
                  :disabled="item.disabled"
                  mode="multiple"
                  :placeholder="item.placeholder"
                  v-model:value="formInfo[item.attr]"
                  v-if="item.type == 'select' && item.mode === 'multiple'"
                  @change="(val:any) => propChange(val, item)"
                >
                  <template v-if="item.options && item.options.length > 0">
                    <a-select-option
                      v-for="oitem in item.options"
                      :title="oitem.label"
                      :value="oitem.value"
                      :key="oitem.value"
                      >{{ oitem.label }}</a-select-option
                    >
                  </template>
                </a-select>
                <template v-if="item.type == 'image'">
                  <x-upload
                    :disabled="item.disabled"
                    v-model:imgList="formInfo[item.attr]"
                    @imgChange="(val:any) => propChange(val, item)"
                  ></x-upload>
                </template>
              </template>
            </a-form-item>
          </a-col>
        </a-row>
      </a-form>
    </a-spin>
  </div>
</template>
<script setup lang="ts">
import dayjs from "dayjs";
import type { PropType } from "vue";
import { ref, unref, watch, onMounted } from "vue";
import { momentToTime } from "./util";

interface dictType {
  type: string;
  attr: string;
  label: string;
  placeholder?: string;
  options?: Array<{ label: string; value: string }>;
  slot?: boolean;
  disabled?: boolean;
  format?: string; // 时间日期格式
  span?: number; // 每行的个数
  fun?: () => Promise<Array<{ label: string; value: string }>>;
}
const formRef = ref();
const showForm = ref(false);
const props = defineProps({
  formDict: {
    type: Array as PropType<Array<dictType>>,
    default: () => {
      return [];
    },
  },
  gutter: {
    type: Number,
    default: 0,
  },
  formValue: {
    type: Object,
    default: () => ({}),
  },
  rules: {
    type: Object,
    default: () => ({}),
  },
  labelCol: {
    type: Object,
    default: () => ({
      span: 6,
    }),
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  wrapperCol: {
    type: Object,
    default: () => ({
      span: 18,
    }),
  },
});

const formInfo = ref<any>({});

const emits = defineEmits(["update:formValue"]);
let timer: any = null;
const propChange = (val: any, item: dictType) => {
  if (timer) {
    clearTimeout(timer);
    timer = null;
  }
  timer = setTimeout(() => {
    emits("update:formValue", momentToTime(formInfo.value));
  }, 500);
};
const dateFormat = "YYYY-MM-DD";
const setInitData = async () => {
  // console.log('初始化值======');
  // console.log(initData);
  const temp: any = {};
  for (let i = 0; i < props.formDict.length; i++) {
    const it = props.formDict[i];
    if (props.disabled) {
      it.disabled = true;
    }

    if (it.type === "select" && it.fun && it.options?.length == 0) {
      it.options = await it.fun();
    }
    const val = props.formValue[it.attr];
    if (it.type === "time" && val) {
      temp[it.attr] = dayjs(
        props.formValue[it.attr],
        it.format || "YYYY-MM-DD"
      );
    }
    if (it.type === "timeRange" && val) {
      temp[it.attr] = [
        dayjs(val[0], it.format || dateFormat),
        dayjs(val[1], it.format || dateFormat),
      ];
    }
  }

  formInfo.value = {
    ...props.formValue,
    ...temp,
  };
  showForm.value = true;
};
onMounted(() => {
  setInitData();
});
watch(
  () => props.formValue,
  (nv, ov) => {
    setInitData();
  },
  {
    deep: true,
  }
);

const checkField = async () => {
  try {
    const values = await formRef.value.validateFields();
    return true;
  } catch (errorInfo) {
    // console.log("Failed:", errorInfo);
    return false;
  }
};

defineExpose({
  checkField,
});
</script>
<script lang="ts">
export default {
  name: "x-form",
};
</script>
<style lang="scss" scoped>
.x_form {
  box-sizing: border-box;
  overflow: hidden;
  overflow-y: scroll;
  width: 100%;
}
</style>
